package main

import (
    "context"
    "encoding/csv"
    "fmt"
	"log"
	"os"
	"path/filepath"
    "go.mongodb.org/mongo-driver/bson"
    "go.mongodb.org/mongo-driver/mongo"
    "math"
    "sort"
    "time"
	"go.mongodb.org/mongo-driver/bson/primitive"
)
// 定义一个结构存储 document 中的 timestamp 和 temperature
type TempRecord struct {
    Timestamp   time.Time
    Temperature float64
}

func runQueryTests(client *mongo.Client, window time.Duration, writer *csv.Writer, threshold float64) {
    collection := client.Database(databaseName).Collection(collectionName)
	var startTime, endTime time.Time
	if BaseTime.IsZero() { // BaseTime 为空
		endTime = time.Now().UTC()
	} else {
		endTime = BaseTime.UTC()
	}

    startTime = endTime.Add(-window)

    fmt.Printf("\n>>> Query window: %s ~ %s\n",
        startTime.Format(time.RFC3339),
        endTime.Format(time.RFC3339))

    var durations []float64
    validQueries := 0

    for i := 1; i <= testCount; i++ {
        sensorID := randomSensorID()

        queryStart := time.Now()
        ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
        defer cancel()

        filter := bson.M{
            "tags.sensor": sensorID,
            "timestamp": bson.M{
                "$gte": startTime,
                "$lt":  endTime,
            },
        }

        cursor, err := collection.Find(ctx, filter)
        if err != nil {
            fmt.Printf("Query %d failed: %v\n", i, err)
            continue
        }

        count := 0
		records := []TempRecord{}
		for cursor.Next(ctx) {
			var doc bson.M
			if err := cursor.Decode(&doc); err == nil {
				count++
				fields, ok1 := doc["fields"].(bson.M)
				ts, ok2 := doc["timestamp"].(primitive.DateTime)
				temp, ok3 := fields["temperature"].(float64)
				if ok1 && ok2 && ok3 {
					records = append(records, TempRecord{
						Timestamp:   ts.Time(),
						Temperature: temp,
					})
				}
			}
		}
		cursor.Close(ctx)

		elapsed := time.Since(queryStart).Seconds()
		durations = append(durations, elapsed)
		if count > 0 {
			validQueries++
		}

		fmt.Printf("Query %d finished, elapsed: %.4f s, count: %d\n", i, elapsed, count)
		if saveResults {
			// 写入 CSV，每条记录单独一行
			for _, rec := range records {
				err := writer.Write([]string{
					sensorID,
					rec.Timestamp.Format("2025-01-02T15:04:05.000Z"),
					fmt.Sprintf("%.6f", rec.Temperature),
				})
				if err != nil {
					fmt.Printf("写入 CSV 失败: %v\n", err)
				}
			}
			writer.Flush()  // 保证数据写入磁盘
		}
    }

    // === 性能指标统计 ===
    //reportPerformance(durations, validQueries, window)
	writePerformanceReport(window, durations, validQueries, testCount, threshold)
}

// 写入性能报告到 TXT 文件
func writePerformanceReport(window time.Duration, durations []float64, validQueries, totalQueries int, threshold float64) {
    // 计算性能指标
    avg, min, max, p95 := calculateStats(durations)

    // 确保 results 目录存在
    resultsDir := "results"
    if err := os.MkdirAll(resultsDir, os.ModePerm); err != nil {
        log.Fatalf("创建结果目录失败: %v", err)
    }

    // 生成报告文件名
    reportFile := filepath.Join(resultsDir, fmt.Sprintf("performance_report_%dG_%v_%s.txt", 
								int(threshold), window, time.Now().Format("2006-01-02_15-04-05")))

    file, err := os.OpenFile(reportFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
    if err != nil {
        log.Fatalf("无法创建性能报告文件: %v", err)
    }
    defer file.Close()

    report := fmt.Sprintf(
        "===== [Performance Report] =====\n"+
            "Time Window      : %s\n"+
            "Average (s)      : %.4f\n"+
            "Min (s)          : %.4f\n"+
            "Max (s)          : %.4f\n"+
            "P95 (s)          : %.4f\n"+
            "Valid Queries    : %d / %d\n"+
            "Timestamp        : %s\n"+
            "===============================\n\n",
        window,
        avg,
        min,
        max,
        p95,
        validQueries,
        totalQueries,
        time.Now().Format("2006-01-02 15:04:05"),
    )

    if _, err := file.WriteString(report); err != nil {
        log.Fatalf("写入性能报告失败: %v", err)
    }

    fmt.Print(report) // 控制台输出
}

// 统计性能指标
func reportPerformance(durations []float64, validQueries int, window time.Duration) {
    if len(durations) == 0 {
        fmt.Printf("\n>>> [Performance] 时间窗口 %v 内无数据。\n", window)
        return
    }

    sort.Float64s(durations)
    min := durations[0]
    max := durations[len(durations)-1]

    sum := 0.0
    for _, d := range durations {
        sum += d
    }
    avg := sum / float64(len(durations))

    // P95
    index := int(math.Ceil(float64(len(durations)) * 0.95))
    if index > len(durations)-1 {
        index = len(durations) - 1
    }
    p95 := durations[index]

    fmt.Printf("\n===== [Performance Report] =====\n")
    fmt.Printf("Time Window      : %v\n", window)
    fmt.Printf("Average (s)      : %.4f\n", avg)
    fmt.Printf("Min (s)          : %.4f\n", min)
    fmt.Printf("Max (s)          : %.4f\n", max)
    fmt.Printf("P95 (s)          : %.4f\n", p95)
    fmt.Printf("Valid Queries    : %d / %d\n", validQueries, len(durations))
    fmt.Println("===============================\n")
}
